package com.uenpay.util.net.retrofit;

import com.socks.library.KLog;
import com.uenpay.util.common.AppConfig;
import com.uenpay.util.crypt.AES;
import com.uenpay.util.crypt.CryptUtils;
import com.uenpay.util.net.http.HttpParam;
import com.uenpay.util.net.http.IHttpManager;
import com.uenpay.util.net.subscribers.UenSubscriber;

import org.json.JSONException;
import org.json.JSONObject;
import org.simpleframework.xml.core.Persister;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import okio.Buffer;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.simplexml.SimpleXmlConverterFactory;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

import static android.content.ContentValues.TAG;

/**
 * Created by liulou on 2016/11/15.
 * desc:
 */

public class HttpManager implements IHttpManager<RetrofitRequest> {

    public static final long HTTP_CONNECT_TIMEOUT = 60 * 1000;
    public static final long HTTP_READ_TIMEOUT = 60 * 1000;
    public static final String SCHEME = AppConfig.HOST_ADDR.isHttps() ? "https://" : "http://";
    public static final String BASE_URL = AppConfig.HOST_ADDR.getAmsPort() == -1 ? SCHEME + AppConfig.HOST_ADDR.getIp() + "/im-app/" : SCHEME + AppConfig.HOST_ADDR.getIp() + ":" + AppConfig.HOST_ADDR.getAmsPort() + "/im-app/";

    private volatile static HttpManager INSTANCE;
    private OkHttpClient mOkHttpClient;
    private Retrofit mRetrofit;
    private Object mService;

    //构造方法私有
    private HttpManager(Class service) {

        mOkHttpClient = new OkHttpClient.Builder()
                .readTimeout(HTTP_READ_TIMEOUT, TimeUnit.MILLISECONDS)
                .connectTimeout(HTTP_CONNECT_TIMEOUT, TimeUnit.MILLISECONDS)
                .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
                .addNetworkInterceptor(new EncryptionInterceptor())
                .addInterceptor(new LoggingInterceptor())
                .build();

        mRetrofit = new Retrofit.Builder()
                .client(mOkHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .baseUrl(BASE_URL)
                .build();

        mService = mRetrofit.create(service);
    }

    //获取单例
    public static HttpManager getInstance(Class service) {
        if (INSTANCE == null) {
            synchronized (HttpManager.class) {
                if (INSTANCE == null) {
                    INSTANCE = new HttpManager(service);
                }
            }
        }
        return INSTANCE;
    }

    @Override
    public void doHttpDeal(RetrofitRequest request) {
        KLog.d(TAG, "doHttpDeal");
        if (mOkHttpClient == null || mRetrofit == null || mService == null) {
            return;
        }
        /*rx处理*/
        UenSubscriber subscriber = new UenSubscriber(request);
        Observable observable = request.getObservable(mService)
                /*http请求线程*/
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                /*回调线程*/
                .observeOn(AndroidSchedulers.mainThread());
        /*数据回调*/
        observable.subscribe(subscriber);
    }

    class LoggingInterceptor implements Interceptor {

        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            long t1 = System.nanoTime();
            KLog.d(TAG, "Sending request: " + request.url());
            Response response = chain.proceed(request);

            long t2 = System.nanoTime();
            KLog.d(TAG, "Received response for " + response.request().url() + " in " + ((t2 - t1) / 1e6d) + " ms");
            return response;
        }
    }

    class EncryptionInterceptor implements Interceptor {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            RequestBody oldBody = request.body();
            Buffer buffer = new Buffer();
            oldBody.writeTo(buffer);
            String strOldBody = buffer.readUtf8();
            MediaType mediaType = MediaType.parse("text/plain; charset=utf-8");
            String strNewBody = AES.encryptString(addPackageMac(strOldBody), CryptUtils.encryptToMD5(AppConfig.PARAMS_ENCRYPT_KEY));
            JSONObject jsonObject = new JSONObject();
            try {
                jsonObject.put("paramsStr", strNewBody);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            RequestBody body = RequestBody.create(mediaType, jsonObject.toString());
            request = request.newBuilder().header("Content-Type", body.contentType().toString()).header("Content-Length", String.valueOf(body.contentLength())).method(request.method(), body).build();
            return chain.proceed(request);
        }
    }

    private String addPackageMac(String reqStr) {
        JSONObject jsonObject = null;
        try {
            jsonObject = new JSONObject(reqStr);
            JSONObject head = jsonObject.getJSONObject("head");
            String packageMac = CryptUtils.encryptToMD5(reqStr);
            head.put("packgeMac", packageMac);
//            KLog.d(TAG, "[addPackageMac] new request param = " + jsonObject.toString());
        } catch (JSONException e) {
            e.printStackTrace();
            KLog.e(TAG, "[addPackageMac] 请求参数json解析失败");
        }
        if (jsonObject == null) {
            return "";
        }
        return jsonObject.toString();
    }
}
